﻿using System;
using System.Collections.Generic;
using System.Data;
using viNews.Classes;
using viNews.Providers;
using visinia.SmartEngine;
using visinia.SmartEngine.Cache;

namespace viNews.Controllers
{
    public class NewsController
    {
        #region CACHE KEYS
        private const string KEY_NEWS = "news_{0}";
        private const string KEY_DRAFT = "newsDraft_{0}";
        private const int NEWS_EXPIRY = 20;
        private const string KEY_NEWS_DESCRIPTION = "newsDescription_{0}";
        private const string KEY_DRAFT_DESCRIPTION = "newsDraftDescription_{0}";
        private const int NEWS_DESCRIPTION_EXPIRY = 20;
        private const string KEY_NEWS_URL = "newsUrl_{0}";
        private const int NEWS_BY_URL_EXPIRY = 20;
        #endregion

        /// <summary>
        /// Adds a news to the date store
        /// </summary>
        /// <param name="news">The news to be added to the data store</param>
        /// <param name="description">The news contents</param>
        /// <returns>The newly added news id</returns>
        public static int AddNews(News news, string description)
        {
            IDataReader dr = viNewsDataProvider.Provider.AddNews(news.Title, news.Date, news.Category, news.ImageUrl, news.Author, news.Summary, news.Publish, news.Url, description);           
            int index = 0;
            while (dr.Read())
            {
                if (dr[0] != Convert.DBNull)
                    index = (int)dr[0];
            }
            dr.Close();
            DataCache.DeleteCacheMultiple("news");
            return index;
        }

        /// <summary>
        /// Deletes a news frome the data store
        /// </summary>
        /// <param name="NewsId">Id of the news to be deleted</param>
        public static void DeleteNews(int NewsId)
        {
            viNewsDataProvider.Provider.DeleteNews(NewsId);
            DataCache.DeleteCacheMultiple("news");
        }

        /// <summary>
        /// Updates a news
        /// </summary>
        /// <param name="news">The news to be updated</param>
        public static void UpdateNews(News news, string description)
        {
            viNewsDataProvider.Provider.UpdateNews(news.NewsId, news.Title, news.Date, news.Category, news.ImageUrl, news.Author, news.Summary, news.Publish, news.Url, description);
            DataCache.DeleteCacheMultiple("news");
        }

        /// <summary>
        /// Gets the specified news
        /// </summary>
        /// <param name="NewsId">The news id to return</param>
        public static News GetNews(int NewsId)
        {
            return GetNews(NewsId, true);
        }

        public static News GetNews(int NewsId, bool PublishOnly)
        {
            string key = string.Format(KEY_NEWS, NewsId);
            News news = (News)DataCache.GetCache(key);
            if (news == null)
            {
                news = FillNews(viNewsDataProvider.Provider.GetNews(NewsId));
                if (news == null)
                    return null;
                DataCache.SetCache(key, news, new TimeSpan(0, NEWS_EXPIRY, 0));
            }
            if (PublishOnly)
            {
                if (news.Publish)
                    return news;
                else
                    return null;
            }
            return news;
        }

        /// <summary>
        /// Gets the description of the specified news
        /// </summary>
        /// <param name="NewsId">The news id whose description to return</param>
        /// <returns>Returns the description as a string</returns>
        public static string GetNewsDescription(int NewsId)
        {
            return GetNewsDescription(NewsId, true);
        }

        /// <summary>
        /// Gets the description of the specified news
        /// </summary>
        /// <param name="NewsId">The news id whose description to return</param>
        /// <returns>Returns the description as a string</returns>
        public static string GetNewsDescription(int NewsId, bool PublishOnly)
        {
            string key = string.Format(KEY_DRAFT_DESCRIPTION, NewsId);
            string description = (string)DataCache.GetCache(key);
            if (description == null)
            {
                IDataReader dr = viNewsDataProvider.Provider.GetNewsDescription(NewsId);
                if (dr.Read())
                {
                    if (!dr.IsDBNull(0))
                    {
                        description = dr.GetString(0);
                        if (description == null)
                        {
                            dr.Close();
                            return null;
                        }
                        // resolve image urls
                        description = ImageController.ResolveImagesForDisplay(description);
                        DataCache.SetCache(key, description, new TimeSpan(0, NEWS_DESCRIPTION_EXPIRY, 0));
                    }
                }
                dr.Close();
            }
            if (PublishOnly)
            {
                if ((GetNews(NewsId)) != null)
                    return description;
                else
                    return null;
            }
            return description;
        }

        /// <summary>
        /// Gets the specified number of news
        /// </summary>
        /// <param name="start">Starting index</param>
        /// <param name="count">Number of news to access</param>
        /// <returns>The list of news</returns>
        public static List<News> GetNews(int start, int count)
        {   // NO CACHE HERE            
            return GetNews(start, count, true);
        }

        /// <summary>
        /// Gets the specified number of news
        /// </summary>
        /// <param name="start">Starting index</param>
        /// <param name="count">Number of news to access</param>
        /// <returns>The list of news</returns>
        public static List<News> GetNews(int start, int count, bool PublishOnly)
        {   // NO CACHE HERE            
            return FillNewsList(viNewsDataProvider.Provider.GetNews(start, count, PublishOnly));
        }

        #region GRIDVIEW HELPERS
        public static DataTable GetNewsDataTable(int startRowIndex, int maximumRows)
        {
            DataTable table = new DataTable();
            DataColumn column;

            column = new DataColumn();
            column.ColumnName = "NewsId";
            table.Columns.Add(column);

            column = new DataColumn();
            column.ColumnName = "Title";
            table.Columns.Add(column);

            column = new DataColumn();
            column.ColumnName = "Date";
            table.Columns.Add(column);
            
            column = new DataColumn();
            column.ColumnName = "Category";
            table.Columns.Add(column);

            column = new DataColumn();
            column.ColumnName = "ImageUrl";
            table.Columns.Add(column);
            
            column = new DataColumn();
            column.ColumnName = "Author";
            table.Columns.Add(column);

            column = new DataColumn();
            column.ColumnName = "Summary";
            table.Columns.Add(column);
            
            column = new DataColumn();
            column.ColumnName = "Publish";
            table.Columns.Add(column);
            
            column = new DataColumn();
            column.ColumnName = "Url";
            table.Columns.Add(column);

            List<News> list = GetNews(startRowIndex, maximumRows, false);
            if (list == null)
                return table;
            News news = new News();
            for (int i = 0; i < list.Count; i++)
            {
                news = list[i];
                table.Rows.Add(new object[] { news.NewsId, news.Title, news.Date, news.Category, news.ImageUrl, news.Author,  news.Summary, news.Publish, news.Url });
            }
            return table;
        }
        /// <summary>
        /// Gets the total news count
        /// </summary>
        /// <returns>Count of all news</returns>
        public static int GetNewsCount()
        {
            if (DataCache.GetCache("newsCount") == null)
            {
                int count = 0;
                IDataReader dr = viNewsDataProvider.Provider.GetNewsCount();
                if (dr.Read())
                {
                    if (!dr.IsDBNull(0))
                    {
                        count = dr.GetInt32(0);
                    }
                }
                dr.Close();
                DataCache.SetCache("newsCount", count, new TimeSpan(0, 20, 0));
            }
            return (int)DataCache.GetCache("newsCount");
        }
        #endregion
                
        /// <summary>
        /// Generates the url for an news
        /// </summary>
        /// <param name="news">The news for which to generate url</param>
        /// <returns>returns the news url</returns>
        private static string GenerateUrl(News news)
        {
            /*****************************************************************************************/
            // News URL = News/Category/SubCategory/NewsId/some.thing.imp.aspx
            /*****************************************************************************************/
            /****** OR *******/
            /*****************************************************************************************/
            // News URL = News/Category/NewsId/some.thing.imp.aspx
            /*****************************************************************************************/
            string key = string.Format(KEY_NEWS_URL, news.NewsId);
            string URL = (string)DataCache.GetCache(key);
            if (URL == null)
            {
                // check if it has a parent
                int parentid = CategoryController.GetParentCategoryId(news.Category);
                if (parentid == 0)
                {// it is a main category                    
                    Category cat = CategoryController.GetCategory(news.Category);
                    if (cat == null)// this category has deleted so just return null
                        return null;
                    string category = cat.Name;
                    // this url has no subcategory
                    string newsId = news.NewsId.ToString();
                    string newsurl = news.Url;
                    URL = BaseController.viNewsUrlSeparator + "/" + category + "/" + newsId + "/" + newsurl + ".aspx";
                }
                else
                {//it is a subcategory
                    Category cat = CategoryController.GetCategory(parentid);
                    if (cat == null)// this category has deleted so just return null
                        return null;
                    string category = cat.Name;
                    string subcategory = CategoryController.GetCategory(news.Category).Name;
                    string newsId = news.NewsId.ToString();
                    string newsurl = news.Url;
                    URL = BaseController.viNewsUrlSeparator + "/" + category + "/" + subcategory + "/" + newsId + "/" + newsurl + ".aspx";
                }
                DataCache.SetCache(key, URL, new TimeSpan(0, NEWS_BY_URL_EXPIRY, 0));
            }
            return URL;
        }

        #region HELPERS
        internal static News FillNews(IDataReader dr)
        {
            while (dr.Read())
            {
                return ActualRead(dr, true);
            }
            return null;
        }
        internal static List<News> FillNewsList(IDataReader dr)
        {
            List<News> list = new List<News>();
            while (dr.Read())
            {
                list.Add(ActualRead(dr, false));
            }
            dr.Close();
            return list;
        }
        private static News ActualRead(IDataReader dr, bool CloseDataReader)
        {
            News news = new News();
            if (dr["NewsId"] != Convert.DBNull)
                news.NewsId = (int)dr["NewsId"];
            if (dr["Title"] != Convert.DBNull)
                news.Title = (string)dr["Title"];
            if (dr["Date"] != Convert.DBNull)
                news.Date = (DateTime)dr["Date"];
            if (dr["Category"] != Convert.DBNull)
                news.Category = (int)dr["Category"];
            if (dr["ImageUrl"] != Convert.DBNull)
                news.ImageUrl = (string)dr["ImageUrl"];
            if (dr["Author"] != Convert.DBNull)
                news.Author = (string)dr["Author"];
            if (dr["Summary"] != Convert.DBNull)
                news.Summary = (string)dr["Summary"];
            if (dr["Publish"] != Convert.DBNull)
                news.Publish = (bool)dr["Publish"];
            if (dr["Url"] != Convert.DBNull)
                news.Url = (string)dr["Url"];
            //update the news image urls and news url
            news.Summary = ImageController.ResolveImagesForDisplay(news.Summary);
            news.Url = WebRoots.GetWebRoot + GenerateUrl(news);
            if(CloseDataReader)
                dr.Close();
            return news;
        }
        #endregion
    }
}
